// Copyright 2012 dmitry.a.novikov@gmail.com
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
// http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// CnsZ::Object declaration


#ifndef _INCLUDED_CNZ_FILER_H_
#define _INCLUDED_CNZ_FILER_H_

#include "object.h"
#include "exception.h"

namespace CnsZ {

  class Handle;

  class Stream : public Object {
  public:
    DECLARE_CNSZ_CLASS(Stream);
    virtual void wrBytes(size_t num, const void* bytes) = 0;
    virtual void rdBytes(size_t num, void* buffer) = 0;
    virtual void wrBytes(size_t num, Stream* other) = 0;
    virtual size_t forward(size_t offset) = 0;
    virtual size_t back(size_t offset) = 0;
    virtual void seek(size_t pos) = 0;
    virtual size_t tell() const = 0;

    static P<Stream> NewMemoryPages(size_t pagesize);
    static P<Stream> NewFlatMemory(Byte* buffer, size_t buffersize);
  };

  class EndOfFile : public Exception {
  public:
    EndOfFile() {}
  };

  class Filer : public Object {
  public:
    DECLARE_CNSZ_CLASS(Filer);

    virtual Stream& stream() = 0;

    virtual void wrInt8(Int8 val) = 0;
    virtual Int8 rdInt8() = 0;
    void wrUInt8(UInt8 val) { wrInt8(val); }
    UInt8 rdUInt8() { return rdInt8(); }
    Filer& operator << (Int8 val) { wrInt8(val); return *this; }
    Filer& operator >> (Int8& val) { val = rdInt8(); return *this; }
    Filer& operator << (UInt8 val) { wrUInt8(val); return *this; }
    Filer& operator >> (UInt8& val) { val = rdUInt8(); return *this; }

    virtual void wrInt16(Int16 val) = 0;
    virtual Int16 rdInt16() = 0;
    void wrUInt16(UInt16 val) { wrInt16(val); }
    UInt16 rdUInt16() { return rdInt16(); }
    Filer& operator << (Int16 val) { wrInt16(val); return *this; }
    Filer& operator >> (Int16& val) { val = rdInt16(); return *this; }
    Filer& operator << (UInt16 val) { wrUInt16(val); return *this; }
    Filer& operator >> (UInt16& val) { val = rdUInt16(); return *this; }

    virtual void wrInt32(Int32 val) = 0;
    virtual Int32 rdInt32() = 0;
    void wrUInt32(UInt32 val) { wrInt32(val); }
    UInt32 rdUInt32() { return rdInt32(); }
    Filer& operator << (Int32 val) { wrInt32(val); return *this; }
    Filer& operator >> (Int32& val) { val = rdInt32(); return *this; }
    Filer& operator << (UInt32 val) { wrUInt32(val); return *this; }
    Filer& operator >> (UInt32& val) { val = rdUInt32(); return *this; }

    virtual void wrInt64(Int64 val) = 0;
    virtual Int64 rdInt64() = 0;
    void wrUInt64(UInt64 val) { wrInt64(val); }
    UInt64 rdUInt64() { return rdInt64(); }
    Filer& operator << (Int64 val) { wrInt64(val); return *this; }
    Filer& operator >> (Int64& val) { val = rdInt64(); return *this; }
    Filer& operator << (UInt64 val) { wrUInt64(val); return *this; }
    Filer& operator >> (UInt64& val) { val = rdUInt64(); return *this; }

    virtual void wrDouble(Double val) = 0;
    virtual Double rdDouble() = 0;
    Filer& operator << (Double val) { wrDouble(val); return *this; }
    Filer& operator >> (Double& val) { val = rdDouble(); return *this; }

    virtual void wrFloat(Float val) = 0;
    virtual Float rdFloat() = 0;
    Filer& operator << (Float val) { wrFloat(val); return *this; }
    Filer& operator >> (Float& val) { val = rdFloat(); return *this; }

    virtual void wrObjectPtr(const Object* val) = 0;
    virtual P<Object> rdObjectPtr() = 0;

    virtual void wrObject(const Object* val) = 0;
    virtual P<Object> rdObject() = 0;

    virtual void wrHandle(const Handle* handle) = 0;
    virtual P<Handle> rdHandle() = 0;
  };

  class CopyFiler : public Filer {
  public:
    DECLARE_CNSZ_CLASS(CopyFiler);

    virtual void setStream(Stream* stream) = 0;

    static P<Filer> New(Stream* stream);
  };
}

#endif //#ifndef _INCLUDED_CNZ_FILER_H_